package com.feinno.module.security.domain;

import java.util.Date;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.OrderBy;
import org.hibernate.annotations.Parameter;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotBlank;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.feinno.framework.common.domain.AbstractEntity;

/**
 * @author cac
 */
@Entity
@Table(name = "SYS_USER")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@JsonIgnoreProperties({ "passwd", "salt" })
public class User extends AbstractEntity {
	/** uid */
	private static final long serialVersionUID = -1740401537348774052L;

	public static final String STATUS_ENABLE = "1";
	public static final String STATUS_DISABLE = "2";

	/** 登陆名 */
	private String loginid;

	/** 密码 */
	private String passwd;

	private String salt;

	/** 名字 */
	private String name;

	/** 电子邮件 */
	private String email;

	/** 状态 1.有效 2.无效 */
	private String status;

	/** 用户类型 1:管理员 2:操作员 3:代理商 4:客户 */
	private String userType;

	private Date createTime = new Date();

	/** 描述 */
	private String descn;

	/** 包含的角色 */
	private Set<Role> roles;

	@Column(name = "USERTYPE")
	public String getUserType() {
		return userType;
	}

	public void setUserType(String userType) {
		this.userType = userType;
	}

	/**
	 * default constructor
	 */
	public User() {
	}

	/**
	 * minimal constructor
	 */
	public User(String loginid, String passwd, String name, String email) {
		this.loginid = loginid;
		this.passwd = passwd;
		this.name = name;
		this.email = email;
	}

	/**
	 * full constructor
	 */
	public User(String loginid, String passwd, String name, String email,
			String status, String descn, Set<Role> roles) {
		this.loginid = loginid;
		this.passwd = passwd;
		this.name = name;
		this.email = email;
		this.status = status;
		this.descn = descn;
		this.roles = roles;
	}

	@Id
	@GeneratedValue(generator = "sequence")
	@GenericGenerator(name = "sequence", strategy = "sequence", parameters = { @Parameter(name = "sequence", value = "SEQ_SYS_USER") })
	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	@NotBlank
	@Column(name = "LOGINID")
	public String getLoginid() {
		return this.loginid;
	}

	public void setLoginid(String loginid) {
		this.loginid = loginid;
	}

	@Column(name = "PASSWD")
	public String getPasswd() {
		return this.passwd;
	}

	public void setPasswd(String passwd) {
		this.passwd = passwd;
	}

	@Column(name = "NAME")
	public String getName() {
		return this.name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Email
	@Column(name = "EMAIL")
	public String getEmail() {
		return this.email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	@Column(name = "STATUS")
	public String getStatus() {
		return this.status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE},
			fetch = FetchType.LAZY,targetEntity = com.feinno.module.security.domain.Role.class)
	@JoinTable(name = "SYS_USER_ROLE", joinColumns = @JoinColumn(name = "USER_ID"), inverseJoinColumns = @JoinColumn(name = "ROLE_ID"))
	@OrderBy(clause = "role_id")
	public Set<Role> getRoles() {
		return this.roles;
	}

	public void setRoles(Set<Role> roles) {
		this.roles = roles;
	}

	@Column(name = "DESCN")
	public String getDescn() {
		return descn;
	}

	public void setDescn(String descn) {
		this.descn = descn;
	}

	@Transient
	public boolean isEnabled() {
		return (this.status != null && !this.status.equals("0"));
	}

	public String getSalt() {
		return salt;
	}

	public void setSalt(String salt) {
		this.salt = salt;
	}

	public Date getCreateTime() {
		return createTime;
	}

	public void setCreateTime(Date createTime) {
		this.createTime = createTime;
	}

	/**
	 * 重载equals,只计算loginid;
	 */
	@Override
	public int hashCode() {
		return HashCodeBuilder.reflectionHashCode(this, "loginid");
	}

	/**
	 * 重载equals,只比较loginid
	 */
	@Override
	public boolean equals(Object obj) {
		return EqualsBuilder.reflectionEquals(this, obj, "loginid");
	}

	@Override
	public String toString() {
		return String.format("%s [%s]", loginid, name);
	}

}
